package web_http

import (
	"bytes"
	"client2/config"
	"crypto/rand"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math/big"
	"net/http"
	"net/url"
	"strconv"
	"time"

	"github.com/consensys/gnark-crypto/ecc/bn254/fr/mimc"
)

// 1.获取设备列表
func GetDevices(baseURL string, page, limit int, status, sensorType string) (*DeviceListResponse, error) {
	// 构建请求URL
	u, err := url.Parse(baseURL + "/api/v1/devices")
	if err != nil {
		return nil, fmt.Errorf("解析URL失败: %v", err)
	}

	// 添加查询参数
	q := u.Query()
	q.Add("page", strconv.Itoa(page))
	q.Add("limit", strconv.Itoa(limit))
	if status != "" {
		q.Add("status", status)
	}
	if sensorType != "" {
		q.Add("sensor_type", sensorType)
	}
	u.RawQuery = q.Encode()

	log.Printf("设备列表请求: %s", u.String())

	// 发送HTTP请求
	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Get(u.String())
	if err != nil {
		return nil, fmt.Errorf("请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 读取完整响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %v", err)
	}

	// 打印原始响应
	log.Printf("GetDevices 响应状态码: %d", resp.StatusCode)
	// log.Printf("响应头: %v", resp.Header)
	log.Printf("GetDevices 响应体: %s", string(body))

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("服务器返回错误状态: %d", resp.StatusCode)
	}

	// 解析响应体
	var response DeviceListResponse
	if err := json.Unmarshal(body, &response); err != nil {
		return nil, fmt.Errorf("解析响应失败: %v", err)
	}

	log.Printf("获取到 %d 个设备 (共 %d 个)", len(response.Devices), response.Total)
	return &response, nil
}

// 1.1 获取储能柜列表
func GetCabinets(baseURL string) (*CabinetListResponse, error) {
	// 构建请求URL
	url := baseURL + "/api/v1/cabinets"

	log.Printf("储能柜列表请求: %s", url)

	// 发送HTTP请求
	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Get(url)
	if err != nil {
		return nil, fmt.Errorf("请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 读取完整响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %v", err)
	}

	// 打印原始响应
	log.Printf("GetCabinets 响应状态码: %d", resp.StatusCode)
	log.Printf("GetCabinets 响应体: %s", string(body))

	// 检查响应状态码
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("服务器返回错误状态: %d", resp.StatusCode)
	}

	// 解析响应体
	var response CabinetListResponse
	if err := json.Unmarshal(body, &response); err != nil {
		return nil, fmt.Errorf("解析响应失败: %v", err)
	}

	log.Printf("获取到 %d 个储能柜", len(response.Cabinets))
	return &response, nil
}

// 2.获取设备详情
func GetDeviceDetails(baseURL, deviceID string) (*DeviceInfo, error) {
	// 构建请求URL
	url := fmt.Sprintf("%s/api/v1/devices/%s", baseURL, deviceID)
	log.Printf("获取设备详情请求: %s", url)

	// 发送HTTP请求
	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Get(url)
	if err != nil {
		return nil, fmt.Errorf("请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 读取完整响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %v", err)
	}

	// 打印原始响应
	log.Printf("GetDeviceDetails 响应状态码: %d", resp.StatusCode)
	//log.Printf("响应体: %s", string(body))

	// 检查响应状态码
	if resp.StatusCode == http.StatusNotFound {
		return nil, fmt.Errorf("设备不存在")
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("服务器返回错误状态: %d", resp.StatusCode)
	}

	// 解析响应体
	var device DeviceInfo
	if err := json.Unmarshal(body, &device); err != nil {
		return nil, fmt.Errorf("解析响应失败: %v", err)
	}

	log.Printf("成功获取设备详情: %s (状态: %s)", device.DeviceID, device.Status)
	return &device, nil
}

// 3.注册设备（支持 SensorDeviceConfig）
func RegisterDevice(sensorConfig *config.SensorDeviceConfig, BASE_URL string) error {
	log.Printf("开始注册设备: %s (类型: %s)...", sensorConfig.DeviceID, sensorConfig.SensorType)

	// ✅ 修复：使用与电路一致的方式计算承诺
	log.Println("计算承诺（MiMC(secret, device_id)）...")

	// 使用 ComputeMiMCHash 确保与电路计算一致
	commitment, err := ComputeMiMCHashForDevice(sensorConfig.Secret, []byte(sensorConfig.DeviceID))
	if err != nil {
		return fmt.Errorf("计算承诺失败: %v", err)
	}
	sensorConfig.Commitment = commitment
	log.Printf("MiMC 承诺生成完成: %s", sensorConfig.Commitment)

	log.Println("生成公钥...")
	publicKey := GenerateRandomPublicKey()
	log.Printf("公钥: %s", publicKey)

	log.Println("准备注册请求...")
	req := RegisterRequest{
		DeviceID:     sensorConfig.DeviceID,
		DeviceType:   "sensor",
		SensorType:   sensorConfig.SensorType, // ✅ 修复：从配置读取
		CabinetID:    "CABINET_A1",
		PublicKey:    publicKey,
		Commitment:   sensorConfig.Commitment,
		Model:        fmt.Sprintf("%s-SENSOR-V1", sensorConfig.SensorType),
		Manufacturer: "EdgeTech Solutions",
		FirmwareVer:  "1.0.0",
	}

	log.Println("序列化请求体...")
	jsonData, err := json.Marshal(req)
	if err != nil {
		return fmt.Errorf("序列化注册请求失败: %v", err)
	}

	log.Println("发送注册请求...")
	url := BASE_URL + "/api/v1/devices"
	log.Printf("请求URL: %s", url)

	client := &http.Client{Timeout: 10 * time.Second}
	resp, err := client.Post(url, "application/json", bytes.NewBuffer(jsonData))
	if err != nil {
		log.Printf("注册请求失败: %v", err)
		return fmt.Errorf("注册请求失败: %v", err)
	}
	defer resp.Body.Close()

	body, _ := io.ReadAll(resp.Body)
	log.Printf("服务器响应状态码: %d", resp.StatusCode)
	log.Printf("服务器响应体: %s", string(body))

	if resp.StatusCode != http.StatusCreated {
		return fmt.Errorf("注册失败，状态码: %d, 响应: %s", resp.StatusCode, string(body))
	}

	// ✅ 修复：解析服务端返回的设备信息
	var registeredDevice DeviceInfo
	if err := json.Unmarshal(body, &registeredDevice); err != nil {
		log.Printf("警告: 解析注册响应失败: %v，使用本地计算的值", err)
	} else {
		// 更新配置：使用服务端返回的 commitment
		if registeredDevice.Commitment != "" {
			sensorConfig.Commitment = registeredDevice.Commitment
			log.Printf("使用服务端返回的 commitment: %s", registeredDevice.Commitment)
		}
	}

	// 标记为已注册
	sensorConfig.Registered = true

	log.Printf("设备 %s 注册成功!", sensorConfig.DeviceID)
	return nil
}

// 4.更新设备信息
func UpdateDevice(baseURL, deviceID string, updateData map[string]interface{}) (*DeviceInfo, error) {
	// 构建请求URL
	url := fmt.Sprintf("%s/api/v1/devices/%s", baseURL, deviceID)
	log.Printf("更新设备请求: %s", url)

	// 序列化请求体
	jsonData, err := json.Marshal(updateData)
	if err != nil {
		return nil, fmt.Errorf("序列化请求体失败: %v", err)
	}

	// 创建PUT请求
	req, err := http.NewRequest(http.MethodPut, url, bytes.NewBuffer(jsonData))
	if err != nil {
		return nil, fmt.Errorf("创建请求失败: %v", err)
	}
	req.Header.Set("Content-Type", "application/json")

	// 发送HTTP请求
	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		return nil, fmt.Errorf("请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 读取完整响应体
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("读取响应失败: %v", err)
	}

	// 打印原始响应
	log.Printf("UpdateDevice 响应状态码: %d", resp.StatusCode)
	log.Printf("UpdateDevice 响应体: %s", string(body))

	// 检查响应状态码
	if resp.StatusCode == http.StatusNotFound {
		return nil, fmt.Errorf("设备不存在")
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("服务器返回错误状态: %d", resp.StatusCode)
	}

	// 解析响应体
	var updatedDevice DeviceInfo
	if err := json.Unmarshal(body, &updatedDevice); err != nil {
		return nil, fmt.Errorf("解析响应失败: %v", err)
	}

	log.Printf("成功更新设备: %s", updatedDevice.DeviceID)
	return &updatedDevice, nil
}

// 检查设备是否在服务端存在（异步安全版本）
func CheckDeviceExists(deviceID string, BASE_URL string) (bool, error) {
	log.Println("检查设备是否存在...")
	log.Printf("设备ID: %s", deviceID)

	url := BASE_URL + "/api/v1/devices/" + deviceID
	log.Printf("请求URL: %s", url)

	// 使用短超时，避免长时间阻塞
	client := &http.Client{Timeout: 5 * time.Second}
	resp, err := client.Get(url)
	if err != nil {
		log.Printf("网络请求失败: %v", err)
		return false, fmt.Errorf("网络请求失败: %v", err)
	}
	defer resp.Body.Close()

	log.Printf("CheckDeviceExists 响应状态码: %d", resp.StatusCode)

	if resp.StatusCode == http.StatusOK {
		log.Println("设备存在")
		return true, nil
	} else if resp.StatusCode == http.StatusNotFound {
		log.Println("设备不存在")
		return false, nil
	}

	body, _ := ioutil.ReadAll(resp.Body)
	log.Printf("CheckDeviceExists 响应体: %s", string(body))
	return false, fmt.Errorf("CheckDeviceExists 服务器返回错误: %s, 响应: %s", resp.Status, string(body))
}

// 生成随机公钥
func GenerateRandomPublicKey() string {
	log.Println("生成随机公钥...")
	b := make([]byte, 32)
	if _, err := rand.Read(b); err != nil {
		log.Printf("生成随机公钥失败: %v", err)
		return "default_public_key_" + time.Now().Format("20060102150405")
	}
	return hex.EncodeToString(b)
}

// ComputeMiMCHashForDevice 计算 MiMC 哈希（与电路一致）
func ComputeMiMCHashForDevice(secretHex string, dataBytes []byte) (string, error) {
	// BN254 scalar field 模数
	modulus, _ := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)

	// Secret 是 hex 字符串，需要解码为字节
	secretBytes, err := hex.DecodeString(secretHex)
	if err != nil {
		return "", fmt.Errorf("解析 secret hex 失败: %v", err)
	}

	// ✅ 关键修复：将 secret 模 r，与电路中的行为一致
	secretBig := new(big.Int).SetBytes(secretBytes)
	secretBig.Mod(secretBig, modulus)
	secretFieldBytes := make([]byte, 32)
	secretBig.FillBytes(secretFieldBytes)

	// ✅ 关键修复：将 data 模 r，与电路中的行为一致
	dataBig := new(big.Int).SetBytes(dataBytes)
	dataBig.Mod(dataBig, modulus)
	dataFieldBytes := make([]byte, 32)
	dataBig.FillBytes(dataFieldBytes)

	// 创建 MiMC 哈希
	h := mimc.NewMiMC()
	h.Write(secretFieldBytes)  // 第一个域元素（32 字节，已模 r）
	h.Write(dataFieldBytes)    // 第二个域元素（32 字节，已模 r）

	// 返回十六进制结果
	result := h.Sum(nil)
	return hex.EncodeToString(result), nil
}
